package com.controller;

import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.IOUtils;
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.entity.InputStreamEntity;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StreamUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.util.UriComponentsBuilder;

import com.util.HttpClientUtil;

@RestController
public class ProxyController2 {

    @RequestMapping(value = "/**")
    public void proxy(HttpServletRequest request, HttpServletResponse response, HttpMethod method)
        throws ClientProtocolException, IOException {
        CloseableHttpClient client = HttpClientUtil.getHttpClient();
        if (method == HttpMethod.GET) {
            HttpGet httpGet = new HttpGet(createRouterUri(request));
            convertRequestHeaderToHTTPRequestBase(request, httpGet);
            HttpResponse httpResponse = client.execute(httpGet);
            convertToServletResponse(response, httpResponse);
        } else if (method == HttpMethod.POST) {
            HttpPost httpPost = new HttpPost(createRouterUri(request));
            convertRequestHeaderToHTTPRequestBase(request, httpPost);
            httpPost.removeHeaders("Content-Length");
            Map<String, String[]> paramsMap = request.getParameterMap();
            List<NameValuePair> nvps = new ArrayList<NameValuePair>();
            Set<String> keySet = paramsMap.keySet();
            for (String key : keySet) {
                String[] values = paramsMap.get(key);
                for (String value : values) {
                    nvps.add(new BasicNameValuePair(key, value));
                    System.out.println(key + ":" + value);
                }
            }
            httpPost.setEntity(new UrlEncodedFormEntity(nvps, "utf-8"));
            HttpResponse httpResponse = client.execute(httpPost);
            convertToServletResponse(response, httpResponse);
        }
    }

    /**
     * HttpClient的HttpResponse转换为HttpServletResponse
     * 
     * @param  response
     * @param  httpResponse
     * @throws UnsupportedOperationException
     * @throws IOException
     */
    private void convertToServletResponse(HttpServletResponse response, HttpResponse httpResponse)
        throws UnsupportedOperationException, IOException {
        System.out.println("---------response heaader----------");
        int statusCode = httpResponse.getStatusLine().getStatusCode();
        response.setStatus(statusCode);
        Header[] headerArray = httpResponse.getAllHeaders();
        for (Header header : headerArray) {
            response.setHeader(header.getName(), header.getValue());
        }
        IOUtils.copy(httpResponse.getEntity().getContent(), response.getOutputStream());
    }

    /**
     * 创建路由信息
     * 
     * @param  request
     * @return
     */
    private URI createRouterUri(HttpServletRequest request) {
        return UriComponentsBuilder.fromHttpUrl("http://localhost:8080/").path(request.getRequestURI())
            .replaceQuery(request.getQueryString()).build().toUri();
    }

    /**
     * 获取请求体内容
     * 
     * @param  request
     * @return
     * @throws IOException
     */
    private byte[] parseRequestBody(HttpServletRequest request) throws IOException {
        InputStream inputStream = request.getInputStream();
        return StreamUtils.copyToByteArray(inputStream);
    }

    /**
     * HttpServletRequest 请求信息转换到 HttpRequestBase中
     * 
     * @param  request
     * @param  baseHeader
     * @return
     */
    private MultiValueMap<String, String> convertRequestHeaderToHTTPRequestBase(HttpServletRequest request,
        HttpRequestBase baseHeader) {
        System.out.println("-------header--start---request@" + request.hashCode());
        HttpHeaders headers = new HttpHeaders();
        List<String> headerNames = Collections.list(request.getHeaderNames());
        for (String headerName : headerNames) {
            System.out.print(headerName + ": ");
            List<String> headerValues = Collections.list(request.getHeaders(headerName));
            for (String headerValue : headerValues) {
                System.out.print(headerValue + " ");
                headers.add(headerName, headerValue);
                baseHeader.addHeader(headerName, headerValue);
            }
            System.out.println();
        }
        System.out.println("-------header--end---request@" + request.hashCode());
        return headers;
    }
}
